home *** CD-ROM | disk | FTP | other *** search
/ Visual Basic Source Code / Visual Basic Source Code.iso / vbsource / apptbk / apptbook.txt < prev    next >
Encoding:
Text File  |  1993-01-06  |  19.2 KB  |  696 lines

  1. ' Variables used to manage grid
  2.  
  3. Dim IgnoreRowChange As Integer
  4. Dim GridInvertRect As RECT
  5. Dim GridInverted As Integer
  6. Dim GridDropRow As Integer
  7.  
  8. ' Drag mode constants to keep track of dragging activity.
  9.  
  10. Dim DragType As Integer         ' type of object being dragged
  11. Dim Dragging As Integer         ' TRUE when dragging is in progress
  12. Dim DragIndex As Integer        ' Optional index of dragged obj
  13. Dim DragRow As Integer          ' Optional row being dragged in grid
  14.  
  15. ' Miscellaneous variables
  16.  
  17. Dim valid%                      ' used as return for DragValid
  18.  
  19. ' Bitmasks to describe valid drag objects
  20.  
  21. Const MASK_NEWAPPT = 1      ' a new appointment
  22. Const MASK_OLDAPPT = 2      ' an old appointment
  23. Const MASK_NONE = 0         ' mask used where no drops are allowed
  24.  
  25. Function ApiRectFromPoint (ctl As Grid, X As Single, Y As Single, r As RECT) As Integer
  26.     
  27.     ' Given a grid control and a coordinate position, this routine
  28.     ' returns a Windows RECT structure containing the pixel
  29.     ' coordinates of the row being pointed at.  The row number is
  30.     ' returned, or -1, indicating that no row is being pointed at.
  31.  
  32.     Dim curRow As Integer
  33.     Dim totHeight As Single
  34.     Dim topLocation As Single
  35.  
  36.     ' Loop through each row, accumulating row height until we reach
  37.     ' the row containing the point.
  38.  
  39.     For curRow = 0 To ctl.Rows - 1
  40.  
  41.         topLocation = totHeight
  42.         totHeight = totHeight + ctl.RowHeight(curRow) + Screen.TwipsPerPixelY
  43.         
  44.         If Y < totHeight Then
  45.  
  46.             ' Convert the twips values into pixel coordinates
  47.  
  48.             ApiRectFromPoint = curRow
  49.  
  50.             r.top = topLocation / Screen.TwipsPerPixelY
  51.             r.bottom = totHeight / Screen.TwipsPerPixelY
  52.             r.left = 0
  53.             r.right = ctl.Width / Screen.TwipsPerPixelY
  54.  
  55.             Exit Function
  56.  
  57.         End If
  58.  
  59.     Next curRow
  60.  
  61.     ApiRectFromPoint = -1           ' indicate failure
  62.  
  63. End Function
  64.  
  65. Sub ApptEdit ()
  66.     
  67.     ' This subroutine moves the data in the current grid row into
  68.     ' the "post-it" editing area.
  69.  
  70.     Dim aText As String
  71.     Dim colonPos As Integer
  72.  
  73.     ' This routine copies appointment data to the edit window
  74.  
  75.     ApptList.Col = 1
  76.  
  77.     aText = ApptList.Text
  78.     colonPos = InStr(aText, ":")
  79.  
  80.     ' If no colon, there's no appointment, so clear the post-it
  81.     ' area.  If there is a colon, fill in the information.
  82.  
  83.     If colonPos = 0 Then
  84.         ApptText.Text = ""
  85.         ApptTime.Text = Format$(0, ApptTime.Format)
  86.         ApptType.Text = ""
  87.     Else
  88.         ApptType.Text = Left$(aText, colonPos - 1)
  89.         ApptText.Text = Mid$(aText, colonPos + 2)
  90.         ApptList.Col = 0
  91.         ApptTime.Text = Format$(ApptList.Text, ApptTime.Format)
  92.     End If
  93.  
  94. End Sub
  95.  
  96. Sub ApptList_DragDrop (Source As Control, X As Single, Y As Single)
  97.     
  98.     ' Drop a new appointment or existing appointment at a new
  99.     ' row position.
  100.  
  101.     Dim aText As String
  102.     Dim i%
  103.  
  104.     If Not EndDragMode(MASK_NEWAPPT Or MASK_OLDAPPT) Then Exit Sub
  105.  
  106.     UnhighlightRow
  107.     IgnoreRowChange = True
  108.  
  109.     If DragType = MASK_NEWAPPT Then
  110.         ApptList.Col = 1
  111.         ApptList.Row = GridDropRow
  112.         ApptList.Text = Source.Tag & ": "
  113.         ApptEdit
  114.     Else
  115.         ApptList.Col = 0
  116.         ApptList.Row = GridDropRow
  117.         aText = ApptList.Text
  118.         ApptList.Row = DragRow
  119.         i% = ChangeApptTime(TimeValue(aText))
  120.     End If
  121.  
  122.     IgnoreRowChange = False
  123.     ApptText.SetFocus
  124.  
  125. End Sub
  126.  
  127. Sub ApptList_DragOver (Source As Control, X As Single, Y As Single, State As Integer)
  128.     
  129.     ' When dragging over the grid, both new and old appointments
  130.     ' are considered.  For both cases, we unhighlight the current
  131.     ' destination row upon leaving the drop zone, and assure that
  132.     ' the row under the point is highlighted otherwise.
  133.  
  134.     If Not DragValid(Source, MASK_NEWAPPT Or MASK_OLDAPPT, State) Then
  135.         Exit Sub
  136.     End If
  137.  
  138.     Select Case State
  139.         Case LEAVE
  140.             UnhighlightRow
  141.         Case Else
  142.             GridDropRow = HighlightRowAtPoint(X, Y)
  143.     End Select
  144.  
  145. End Sub
  146.  
  147. Sub ApptList_MouseDown (Button As Integer, Shift As Integer, X As Single, Y As Single)
  148.     
  149.     ' We take charge of the mouse down event to initiate dragging
  150.     ' ourselves.  First, the cursor must be in column 1.  Next,
  151.     ' the row must contain a valid appointment to be grabbed
  152.     ' (identified by the presence of a colon in the cell).
  153.  
  154.     If AtGridCol(ApptList, X, Y) > 0 Then
  155.         If InStr(ApptList.Text, ":") <> 0 Then
  156.  
  157.             ' The timer will now count down.  This allows the user
  158.             ' to easily click, or "press" the mouse.  The Timer
  159.             ' event handles the drag initialization.
  160.  
  161.             GridTimer.Enabled = True
  162.  
  163.         End If
  164.     End If
  165.  
  166. End Sub
  167.  
  168. Sub ApptList_MouseUp (Button As Integer, Shift As Integer, X As Single, Y As Single)
  169.  
  170.     ' Be sure the timer is disabled so that a click doesn't
  171.     ' initiate a drag.  If it's already disabled, it doesn't matter.
  172.  
  173.     GridTimer.Enabled = False
  174.  
  175. End Sub
  176.  
  177. Sub ApptList_RowColChange ()
  178.     
  179.     ' Whenever the row changes, move the highlight to track the
  180.     ' current cell.
  181.  
  182.     ApptList.SelStartRow = ApptList.Row
  183.     ApptList.SelEndRow = ApptList.Row
  184.  
  185.     ' IgnoreRowChange means that we're setting Col or Row somewhere
  186.     ' else in the code and we don't want ApptEdit to be called.
  187.     ' Otherwise, the user changed the row and we update the
  188.     ' "post-it" area.
  189.  
  190.     If Not IgnoreRowChange Then
  191.         IgnoreRowChange = True
  192.         ApptEdit
  193.         IgnoreRowChange = False
  194.     End If
  195.  
  196. End Sub
  197.  
  198. Sub ApptText_DragDrop (Source As Control, X As Single, Y As Single)
  199.     valid% = EndDragMode(MASK_NONE)
  200. End Sub
  201.  
  202. Sub ApptText_DragOver (Source As Control, X As Single, Y As Single, State As Integer)
  203.     valid% = DragValid(Source, MASK_NONE, State)
  204. End Sub
  205.  
  206. Sub ApptTime_DragDrop (Source As Control, X As Single, Y As Single)
  207.     valid% = EndDragMode(MASK_NONE)
  208. End Sub
  209.  
  210. Sub ApptTime_DragOver (Source As Control, X As Single, Y As Single, State As Integer)
  211.     valid% = DragValid(Source, MASK_NONE, State)
  212. End Sub
  213.  
  214. Sub ApptTime_ValidationError (InvalidText As String, StartPosition As Integer)
  215.     
  216.     MsgBox "Invalid time"
  217.     ApptTime.SetFocus
  218.  
  219. End Sub
  220.  
  221. Sub ApptType_DragDrop (Source As Control, X As Single, Y As Single)
  222.     
  223.     ' Accept a drop only for a NEWAPPT icon, otherwise the
  224.     ' operation will be cancelled.
  225.  
  226.     If EndDragMode(MASK_NEWAPPT) Then
  227.         ApptType.Text = Source.Tag
  228.     End If
  229.  
  230. End Sub
  231.  
  232. Sub ApptType_DragOver (Source As Control, X As Single, Y As Single, State As Integer)
  233.     valid% = DragValid(Source, MASK_NEWAPPT, State)
  234. End Sub
  235.  
  236. Sub ApptType_KeyPress (KeyAscii As Integer)
  237.     
  238.     ' Don't allow a colon to be entered, since we use a colon to
  239.     ' separate the appointment "kind" from the text.
  240.  
  241.     If KeyAscii = Asc(":") Then
  242.         Beep
  243.         KeyAscii = 0
  244.     End If
  245.  
  246. End Sub
  247.  
  248. Function AtGridCol (ctl As Control, X As Single, Y As Single)
  249.     
  250.     ' Given a point on a grid control, in twips, this routine
  251.     ' returns the column number where the point is located, or
  252.     ' -1 indicating the point is outside the grid.
  253.  
  254.     Dim curCol As Integer
  255.     Dim totWidth As Single
  256.  
  257.     ' Loop through each column, accumulating column width until we
  258.     ' reach the column containing the point.
  259.  
  260.     For curCol = 0 To ctl.Cols - 1
  261.         
  262.         totWidth = totWidth + ctl.ColWidth(curCol) + Screen.TwipsPerPixelX
  263.         
  264.         If X < totWidth Then
  265.             AtGridCol = curCol
  266.             Exit Function
  267.         End If
  268.  
  269.     Next curCol
  270.  
  271.     AtGridCol = -1          ' not found
  272.  
  273. End Function
  274.  
  275. Sub BeginDragMode (ctl As Control, objType As Integer)
  276.     
  277.     ' Whenever a drag is about to start, this routine is called.
  278.     ' The type mask of the drag is flagged, and we remember that
  279.     ' dragging is in progress.   This routine MUST be matched
  280.     ' by an EndDragMode function call.
  281.  
  282.     DragType = objType
  283.     Dragging = True
  284.  
  285.     ' Start the drag process
  286.  
  287.     ctl.Drag BEGIN_DRAG
  288.  
  289. End Sub
  290.  
  291. Function ChangeApptTime (newtime As Variant) As Integer
  292.     
  293.     ' Given a new time for an appointment at the current row, this
  294.     ' routine moves the appointment to the new location in the
  295.     ' grid.
  296.  
  297.     Dim trow As Integer
  298.     Dim oldAppt As String
  299.  
  300.     trow = TimeRow(newtime)
  301.  
  302.     ' If we're already there, then do nothing and return False,
  303.     ' indicating no row change occurred.
  304.  
  305.     If trow = ApptList.Row Then
  306.         ChangeApptTime = False
  307.         Exit Function
  308.     End If
  309.  
  310.     ChangeApptTime = True
  311.     IgnoreRowChange = True
  312.  
  313.     ' Actually move the row.
  314.  
  315.     ApptList.Col = 1
  316.     oldAppt = ApptList.Text
  317.     ApptList.Text = ""
  318.  
  319.     ApptList.Row = trow
  320.     ApptList.Text = oldAppt
  321.  
  322.     ApptEdit            ' move the data to the post-it area
  323.  
  324.     IgnoreRowChange = False
  325.  
  326. End Function
  327.  
  328. Function DragValid (src As Control, mask As Integer, State As Integer) As Integer
  329.     
  330.     ' This function is called by an object's DragOver event to
  331.     ' automatically change the drag cursor to the "no drop"
  332.     ' cursor if necessary.  It also returns True if the object
  333.     ' can legally be dropped according to the input mask.
  334.  
  335.     If (mask And DragType) Then
  336.         DragValid = True
  337.         Exit Function
  338.     End If
  339.  
  340.     ' This is not a valid drag.  Return False, but also change the
  341.     ' object's drag icon to the NoDrag icon (remembering the old
  342.     ' value for later restore when we exit this object).
  343.  
  344.     DragValid = False
  345.  
  346.     Select Case State
  347.         
  348.         Case ENTER
  349.  
  350.             ' Entering, remember old icon
  351.  
  352.             SaveIcon.DragIcon = src.DragIcon
  353.             src.DragIcon = NoDrag.DragIcon
  354.  
  355.         Case LEAVE
  356.             
  357.             ' Exiting, restore old icon
  358.  
  359.             src.DragIcon = SaveIcon.DragIcon
  360.  
  361.     End Select
  362.                 
  363. End Function
  364.  
  365. Function EndDragMode (mask As Integer) As Integer
  366.     
  367.     ' This function is called when a drag has ended, either
  368.     ' successfully or unsuccessfully.  This routine removes any
  369.     ' user feedback related to the drag operation and returns
  370.     ' TRUE if the passed mask matches the dragged object.
  371.  
  372.     Select Case DragType
  373.  
  374.         Case MASK_NEWAPPT
  375.  
  376.             ' If a "new appointment" icon was dragged, change the
  377.             ' frame background to LTGREY again so that the drag
  378.             ' is officially over.
  379.  
  380.             KindFrame(DragIndex).BackColor = LTGREY
  381.  
  382.         Case MASK_OLDAPPT
  383.  
  384.             ' If this is an item dragged from the grid, refresh
  385.             ' the grid in case the drag ended outside the grid
  386.             ' frame (and the inverted row remains).
  387.  
  388.             ApptList.Refresh
  389.  
  390.     End Select
  391.  
  392.     Dragging = False
  393.     EndDragMode = (mask And DragType) <> 0
  394.     
  395. End Function
  396.  
  397. Sub Form_DragDrop (Source As Control, X As Single, Y As Single)
  398.     
  399.     ' Ignore drops which occur on the form
  400.  
  401.     valid% = EndDragMode(MASK_NONE)
  402.  
  403. End Sub
  404.  
  405. Sub Form_DragOver (Source As Control, X As Single, Y As Single, State As Integer)
  406.     
  407.     ' Assure that the "no drop" icon is displayed when passing
  408.     ' over the form.
  409.  
  410.     valid% = DragValid(Source, MASK_NONE, State)
  411.  
  412. End Sub
  413.  
  414. Sub Form_Load ()
  415.     
  416.     Dim curTime As Variant
  417.     Dim curRow As Integer
  418.     Dim rowMax As Integer
  419.  
  420.     ' Initialize the grid column widths, and set the height of
  421.     ' the list so it displays all times entered.
  422.  
  423.     rowMax = (Prefs.timeEnd - Prefs.timeStart) / Prefs.timeIncrement
  424.     ApptList.ColWidth(0) = ApptForm.TextWidth("XX:XX XX")
  425.     ApptList.ColWidth(1) = ApptList.Width - ApptList.ColWidth(0)
  426.  
  427.     ApptList.Height = (ApptList.RowHeight(0) + Screen.TwipsPerPixelY) * rowMax
  428.  
  429.     IgnoreRowChange = True
  430.  
  431.     ApptList.Rows = rowMax
  432.     ApptList.Col = 0
  433.     
  434.     ' Fill the leftmost column with appointment times.
  435.  
  436.     For curTime = Prefs.timeStart To Prefs.timeEnd Step Prefs.timeIncrement
  437.         ApptList.Row = curRow
  438.         ApptList.Text = Format$(curTime, "hh:mm am/pm")
  439.         curRow = curRow + 1
  440.     Next curTime
  441.  
  442.     IgnoreRowChange = False
  443.     ApptList.Row = 0
  444.  
  445. End Sub
  446.  
  447. Sub Form_MouseMove (Button As Integer, Shift As Integer, X As Single, Y As Single)
  448.     
  449.     ' Since we can't trap a "drop" which occurs outside of our
  450.     ' application, this is a pretty good solution.  Whenever the
  451.     ' cursor passes over the form, if we're still dragging check
  452.     ' to see if the button is now up.  If so, just cancel the
  453.     ' operation
  454.  
  455.     If Dragging Then
  456.         If (Button And LEFT_BUTTON) = 0 Then
  457.             valid% = EndDragMode(MASK_NONE)
  458.         End If
  459.     End If
  460.  
  461. End Sub
  462.  
  463. Sub GridTimer_Timer ()
  464.     
  465.     ' When the timer is triggered, the user has been holding the
  466.     ' mouse down over a grid row for a "press" duration.  Now,
  467.     ' initiate a drag operation.
  468.  
  469.     ' Reset the column to the one with the text in it.
  470.  
  471.     IgnoreRowChange = True
  472.     ApptList.Col = 1
  473.     IgnoreRowChange = False
  474.  
  475.     ' Indicate we're doing an "old appointment" drag.
  476.  
  477.     DragRow = ApptList.Row
  478.     ApptList.DragIcon = MoveIcon.DragIcon
  479.     BeginDragMode ApptList, MASK_OLDAPPT
  480.     GridTimer.Enabled = False
  481.  
  482. End Sub
  483.  
  484. Function HighlightRowAtPoint (X As Single, Y As Single) As Integer
  485.     
  486.     ' If the ApplList grid was highlighted (according to the
  487.     ' GridInverted variable), then unhighlight the old location and
  488.     ' highlight the new one.  Instead of a row number, a point within
  489.     ' the grid is passed.  The row number is returned, or -1, meaning
  490.     ' that the point was outside the grid.
  491.  
  492.     Dim newrect As RECT
  493.     Dim rownum As Integer
  494.     Dim gridDC As Integer
  495.  
  496.     rownum = ApiRectFromPoint(ApptList, X, Y, newrect)
  497.     HighlightRowAtPoint = rownum
  498.  
  499.     ' Don't rehighlight the current row, just exit.
  500.  
  501.     If rownum >= 0 And GridInverted And newrect.top = GridInvertRect.top Then Exit Function
  502.  
  503.     ' Use the Windows API call InvertRect to invert the row we're
  504.     ' passing above.
  505.  
  506.     gridDC = GetDC(ApptList.hWnd)
  507.  
  508.     If GridInverted Then InvertRect gridDC, GridInvertRect
  509.     GridInverted = True
  510.  
  511.     If rownum >= 0 Then
  512.         GridInvertRect = newrect
  513.         InvertRect gridDC, GridInvertRect
  514.         GridInverted = True
  515.     Else
  516.         GridInverted = False
  517.     End If
  518.  
  519.     gridDC = ReleaseDC(ApptList.hWnd, gridDC)
  520.  
  521. End Function
  522.  
  523. Sub Image1_DragDrop (Source As Control, X As Single, Y As Single)
  524.     valid% = EndDragMode(MASK_NONE)
  525. End Sub
  526.  
  527. Sub Image1_DragOver (Source As Control, X As Single, Y As Single, State As Integer)
  528.     valid% = DragValid(Source, MASK_NONE, State)
  529. End Sub
  530.  
  531. Sub KindFrame_DragDrop (Index As Integer, Source As Control, X As Single, Y As Single)
  532.     valid% = EndDragMode(MASK_NONE)
  533. End Sub
  534.  
  535. Sub KindFrame_DragOver (Index As Integer, Source As Control, X As Single, Y As Single, State As Integer)
  536.     valid% = DragValid(Source, MASK_NEWAPPT, State)
  537. End Sub
  538.  
  539. Sub KindPict_DragDrop (Index As Integer, Source As Control, X As Single, Y As Single)
  540.     valid% = EndDragMode(MASK_NONE)
  541. End Sub
  542.  
  543. Sub KindPict_DragOver (Index As Integer, Source As Control, X As Single, Y As Single, State As Integer)
  544.     valid% = DragValid(Source, MASK_NEWAPPT, State)
  545. End Sub
  546.  
  547. Sub KindPict_MouseDown (Index As Integer, Button As Integer, Shift As Integer, X As Single, Y As Single)
  548.     
  549.     ' When the left button goes down over an "appointment type"
  550.     ' icon, drag its image in NEWAPPT mode.  Copy the DragIcon
  551.     ' each time, since it may still be set to the "no drop" icon
  552.     ' from a previous cancellation.
  553.  
  554.     If Button And LEFT_BUTTON Then
  555.  
  556.         KindFrame(Index).DragIcon = DragArrow.DragIcon
  557.         BeginDragMode KindFrame(Index), MASK_NEWAPPT
  558.         KindFrame(Index).BackColor = CYAN
  559.         
  560.         ' Save the index, we'll need it in EndDragMode
  561.  
  562.         DragIndex = Index
  563.  
  564.     End If
  565.  
  566. End Sub
  567.  
  568. Sub Label1_DragDrop (Source As Control, X As Single, Y As Single)
  569.     valid% = EndDragMode(MASK_NONE)
  570. End Sub
  571.  
  572. Sub Label1_DragOver (Source As Control, X As Single, Y As Single, State As Integer)
  573.     valid% = DragValid(Source, MASK_NONE, State)
  574. End Sub
  575.  
  576. Sub Label2_DragDrop (Source As Control, X As Single, Y As Single)
  577.     valid% = EndDragMode(MASK_NONE)
  578. End Sub
  579.  
  580. Sub Label2_DragOver (Source As Control, X As Single, Y As Single, State As Integer)
  581.     valid% = DragValid(Source, MASK_NONE, State)
  582. End Sub
  583.  
  584. Sub Panel3D1_DragDrop (Source As Control, X As Single, Y As Single)
  585.     valid% = EndDragMode(MASK_NONE)
  586. End Sub
  587.  
  588. Sub Panel3D1_DragOver (Source As Control, X As Single, Y As Single, State As Integer)
  589.     valid% = DragValid(Source, MASK_NONE, State)
  590. End Sub
  591.  
  592. Sub SaveButton_Click ()
  593.     
  594.     ' Save all data in the post-it area to the grid.
  595.  
  596.     Dim i%
  597.     
  598.     IgnoreRowChange = True
  599.     ApptList.Col = 1
  600.     
  601.     ' We can only save if there's an appointment on the current
  602.     ' grid row already (at least a blank one).
  603.  
  604.     If InStr(ApptList.Text, ":") = 0 Then
  605.         MsgBox "No appointment at current row"
  606.         Exit Sub
  607.     End If
  608.     
  609.     ApptList.Text = ApptType.Text & ": " & ApptText.Text
  610.     IgnoreRowChange = False
  611.     
  612.     ' If the time was changed manually, then move the row to the new
  613.     ' location.
  614.  
  615.     i% = ChangeApptTime(TimeValue(ApptTime.Text))
  616.  
  617. End Sub
  618.  
  619. Sub SaveButton_DragOver (Source As Control, X As Single, Y As Single, State As Integer)
  620.     valid% = DragValid(Source, MASK_NONE, State)
  621. End Sub
  622.  
  623. Function TimeRow (thetime As Variant) As Integer
  624.     
  625.     ' Given a time value, return the row number within the grid
  626.     ' where the specified time slot is located.
  627.  
  628.     TimeRow = (thetime - Prefs.timeStart) / Prefs.timeIncrement
  629.  
  630. End Function
  631.  
  632. Sub TrashCan_DragDrop (Source As Control, X As Single, Y As Single)
  633.     
  634.     ' The trash can only accepts drops for "old appointments" from
  635.     ' the grid.
  636.  
  637.     If EndDragMode(MASK_OLDAPPT) Then
  638.  
  639.         ' Get rid of feedback
  640.  
  641.         TrashCan.Picture = TrashClosed.Picture
  642.  
  643.         ' Clear the grid row and update the post-it area
  644.  
  645.         IgnoreRowChange = True
  646.         
  647.         ApptList.Row = DragRow
  648.         ApptList.Col = 1
  649.         ApptList.Text = ""
  650.         ApptEdit
  651.         ApptList.SetFocus
  652.  
  653.         IgnoreRowChange = False
  654.  
  655.     End If
  656.  
  657. End Sub
  658.  
  659. Sub TrashCan_DragOver (Source As Control, X As Single, Y As Single, State As Integer)
  660.     
  661.     ' Provide feedback by "opening the trashcan" whenever an
  662.     ' old appointment is dragged over the trash.
  663.  
  664.     If DragValid(Source, MASK_OLDAPPT, State) Then
  665.         Select Case State
  666.             Case ENTER
  667.                 ' Open when entering
  668.                 TrashCan.Picture = TrashOpened.Picture
  669.             Case LEAVE
  670.                 ' Close when leaving
  671.                 TrashCan.Picture = TrashClosed.Picture
  672.         End Select
  673.     End If
  674. End Sub
  675.  
  676. Sub UnhighlightRow ()
  677.     
  678.     ' If the ApptList grid is highlighted (according to the
  679.     ' GridInverted flag), then unhighlight it, otherwise do
  680.     ' nothing.
  681.  
  682.     Dim gridDC As Integer
  683.  
  684.     If Not GridInverted Then Exit Sub
  685.  
  686.     ' Use the invert rectangle saved by HighlightRowAtPoint
  687.  
  688.     gridDC = GetDC(ApptList.hWnd)
  689.     InvertRect gridDC, GridInvertRect
  690.     gridDC = ReleaseDC(ApptList.hWnd, gridDC)
  691.  
  692.     GridInverted = False
  693.  
  694. End Sub
  695.  
  696.